gusucode.com > VC++ EMF图片浏览器(可读emf、wmf、emz、wmz、png……等)-源码程序 > VC++ EMF图片浏览器(可读emf、wmf、emz、wmz、png……等)-源码程序/code/Src/Client/scemflib/SCEMFgdiParser.cpp
//Download by http://www.NewXing.com /* * This file is part of the EMFexplorer projet. * Copyright (C) 2004 Smith Charles. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * * Extension: for commercial use, apply the Equity Public License, which * adds to the normal terms of the GLPL a condition of donation to the author. * If you are interested in support for this source code, * contact Smith Charles <smith.charles@free.fr> for more information. */ #include "stdafx.h" #include "SCEMFgdiParser.h" #include "SCEMFRasterizerDefs.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #include "SCEMFDefs.h" #include "SCGenInclude.h" #include SC_INC_WINLIB(SCDCCloner.h) // to allow token pasting at the beginig of line #define SC_TKNPASTE(fake) #define SC_RECORD_DECL0(recType) \ SC_TKNPASTE(nothing)##recType *pRec = (##recType*)m_pRecord; \ if (pRec->emr.nSize < sizeof(##recType)) \ return SC_BRK_NOERROR #define SC_RECORD_DECL_PLAY(recType) \ SC_TKNPASTE(nothing)##recType *pRec = (##recType*)m_pRecord; \ if (pRec->emr.nSize < sizeof(##recType)) \ { \ SCPlayRecord(); \ return SC_BRK_NOERROR; \ } // Reminder #ifndef SC_RENDERER_CAN_DOROP // Warning: when m_hPlayDC is not a clone, calling functions like SetMapmode on it may // perturbate GDI+. This was observed for printer DC. #pragma message(__FILE__ "(47): SC_RENDERER_CAN_DOROP not defined. Potential printing problems.") #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CSCEMFgdiParser::CSCEMFgdiParser(): SCBrkEMF(), m_pRenderer(NULL), m_hDestDC(NULL) #ifdef SC_USE_DCCLONER ,m_pCloneDC(NULL) #endif { memset(&m_xformOrig, 0, sizeof(m_xformOrig)); m_xformOrig.eM11 = m_xformOrig.eM22 = 1; } CSCEMFgdiParser::CSCEMFgdiParser(I_EMFRenderer* pRenderer): SCBrkEMF(), m_pRenderer(pRenderer), m_hDestDC(NULL) #ifdef SC_USE_DCCLONER ,m_pCloneDC(NULL) #endif { memset(&m_xformOrig, 0, sizeof(m_xformOrig)); m_xformOrig.eM11 = m_xformOrig.eM22 = 1; } CSCEMFgdiParser::~CSCEMFgdiParser() { #ifdef SC_USE_DCCLONER // delete temporary DC if (m_pCloneDC) delete m_pCloneDC; #endif } void CSCEMFgdiParser::SCResetCracker() { } ////////////////////////////////////////////////////////////////////// // Events methods ////////////////////////////////////////////////////////////////////// SC_BRKRESULT CSCEMFgdiParser::OnEmfHEADER() { // TRACE0("**EMR_HEADER\n"); ASSERT(m_pRenderer); //ENHMETAHEADER *pRec = (ENHMETAHEADER*)m_pRecord; SCPlayRecord(); m_pRenderer->SCBeginRendering(m_hDestDC, m_hPlayDC); return SCBrkEMF::OnEmfHEADER(); } SC_BRKRESULT CSCEMFgdiParser::OnEmfPOLYBEZIER() { // TRACE0("**EMR_POLYBEZIER\n"); ASSERT(m_pRenderer); EMRPOLYBEZIER *pRec = (EMRPOLYBEZIER*)m_pRecord; m_pRenderer->SCDrawBezier((LPPOINT)pRec->aptl, pRec->cptl); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfPOLYGON() { // TRACE0("**EMR_POLYGON\n"); ASSERT(m_pRenderer); EMRPOLYGON *pRec = (EMRPOLYGON*)m_pRecord; m_pRenderer->SCDrawPolygon((LPPOINT)pRec->aptl, pRec->cptl); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfPOLYLINE() { // TRACE0("**EMR_POLYLINE\n"); ASSERT(m_pRenderer); EMRPOLYLINE *pRec = (EMRPOLYLINE*)m_pRecord; m_pRenderer->SCDrawLines((LPPOINT)pRec->aptl, pRec->cptl); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfPOLYBEZIERTO() { // TRACE0("**EMR_POLYBEZIERTO\n"); ASSERT(m_pRenderer); EMRPOLYBEZIERTO *pRec = (EMRPOLYBEZIERTO*)m_pRecord; m_pRenderer->SCDrawBezierTo((LPPOINT)pRec->aptl, pRec->cptl); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfPOLYLINETO() { // TRACE0("**EMR_POLYLINETO\n"); ASSERT(m_pRenderer); EMRPOLYLINETO *pRec = (EMRPOLYLINETO*)m_pRecord; m_pRenderer->SCDrawLinesTo((LPPOINT)pRec->aptl, pRec->cptl); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfPOLYPOLYLINE() { // TRACE0("**EMR_POLYPOLYLINE\n"); ASSERT(m_pRenderer); EMRPOLYPOLYLINE *pRec = (EMRPOLYPOLYLINE*)m_pRecord; LPPOINT pPts = (LPPOINT)((DWORD*)pRec->aPolyCounts + pRec->nPolys); m_pRenderer->SCDrawPolyPolyline(pPts, pRec->cptl, (DWORD*)pRec->aPolyCounts, pRec->nPolys); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfPOLYPOLYGON() { // TRACE0("**EMR_POLYPOLYGON\n"); ASSERT(m_pRenderer); EMRPOLYPOLYGON *pRec = (EMRPOLYPOLYGON*)m_pRecord; LPPOINT pPts = (LPPOINT)((DWORD*)pRec->aPolyCounts + pRec->nPolys); m_pRenderer->SCDrawPolyPolygon(pPts, pRec->cptl, (DWORD*)pRec->aPolyCounts, pRec->nPolys); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSETWINDOWEXTEX() { // TRACE0("**EMR_SETWINDOWEXTEX\n"); ASSERT(m_pRenderer); #ifndef SC_RENDERER_CAN_DOROP SCPlayRecord(); // required for ROP management #endif m_pRenderer->SCSetWindowExtent(((EMRSETWINDOWEXTEX*)m_pRecord)->szlExtent.cx, ((EMRSETWINDOWEXTEX*)m_pRecord)->szlExtent.cy); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSETWINDOWORGEX() { // TRACE0("**EMR_SETWINDOWORGEX\n"); ASSERT(m_pRenderer); #ifndef SC_RENDERER_CAN_DOROP SCPlayRecord(); // required for ROP management #endif m_pRenderer->SCSetWindowOrg(((EMRSETWINDOWORGEX*)m_pRecord)->ptlOrigin.x, ((EMRSETWINDOWORGEX*)m_pRecord)->ptlOrigin.y); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSETVIEWPORTEXTEX() { // TRACE0("**EMR_SETVIEWPORTEXTEX\n"); ASSERT(m_pRenderer); #ifndef SC_RENDERER_CAN_DOROP SCPlayRecord(); // required for ROP management #endif m_pRenderer->SCSetViewportExtent(((EMRSETVIEWPORTEXTEX*)m_pRecord)->szlExtent.cx, ((EMRSETVIEWPORTEXTEX*)m_pRecord)->szlExtent.cy); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSETVIEWPORTORGEX() { // TRACE0("**EMR_SETVIEWPORTORGEX\n"); ASSERT(m_pRenderer); #ifndef SC_RENDERER_CAN_DOROP SCPlayRecord(); // required for ROP management #endif m_pRenderer->SCSetViewportOrg(((EMRSETVIEWPORTORGEX*)m_pRecord)->ptlOrigin.x, ((EMRSETVIEWPORTORGEX*)m_pRecord)->ptlOrigin.y); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSETBRUSHORGEX() { // TRACE0("**EMR_SETBRUSHORGEX\n"); ASSERT(m_pRenderer); #ifndef SC_RENDERER_CAN_DOROP SCPlayRecord(); // required for ROP management (via stretchbltmode and halftone) #endif m_pRenderer->SCSetBrushOrg(((EMRSETBRUSHORGEX*)m_pRecord)->ptlOrigin); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfEOF() { // TRACE0("**EMR_EOF\n"); ASSERT(m_pRenderer); // (EMREOF*)m_pRecord; SCPlayRecord(); m_pRenderer->SCEndRendering(); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSETPIXELV() { // TRACE0("**EMR_SETPIXELV\n"); ASSERT(m_pRenderer); m_pRenderer->SCDrawPixel(((EMRSETPIXELV*)m_pRecord)->ptlPixel, ((EMRSETPIXELV*)m_pRecord)->crColor); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSETMAPPERFLAGS() { // TRACE0("**EMR_SETMAPPERFLAGS\n"); ASSERT(m_pRenderer); // (EMRSETMAPPERFLAGS*)m_pRecord; // No aspect ratio management, as we only use TT fonts. // Anyway let Windows do it. SCPlayRecord(); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSETMAPMODE() { // TRACE0("**EMR_SETMAPMODE\n"); ASSERT(m_pRenderer); #ifndef SC_RENDERER_CAN_DOROP SCPlayRecord(); // required for ROP management (via viewport/window settings) #endif m_pRenderer->SCSetMapMode(((EMRSETMAPMODE*)m_pRecord)->iMode); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSETBKMODE() { // TRACE0("**EMR_SETBKMODE\n"); ASSERT(m_pRenderer); //SCPlayRecord(); // wait and see m_pRenderer->SCSetBkMode(((EMRSETBKMODE*)m_pRecord)->iMode); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSETPOLYFILLMODE() { // TRACE0("**EMR_SETPOLYFILLMODE\n"); ASSERT(m_pRenderer); m_pRenderer->SCSetPolyFillMode(((EMRSETPOLYFILLMODE*)m_pRecord)->iMode); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSETROP2() { // TRACE0("**EMR_SETROP2\n"); ASSERT(m_pRenderer); m_pRenderer->SCSetROP2(((EMRSETROP2*)m_pRecord)->iMode); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSETSTRETCHBLTMODE() { // TRACE0("**EMR_SETSTRETCHBLTMODE\n"); ASSERT(m_pRenderer); #ifndef SC_RENDERER_CAN_DOROP SCPlayRecord(); // required for ROP management #endif m_pRenderer->SCSetStretchBltMode(((EMRSETSTRETCHBLTMODE*)m_pRecord)->iMode); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSETTEXTALIGN() { // TRACE0("**EMR_SETTEXTALIGN\n"); ASSERT(m_pRenderer); m_pRenderer->SCSetTextAlign(((EMRSETTEXTALIGN*)m_pRecord)->iMode); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSETCOLORADJUSTMENT() { // TRACE0("**EMR_SETCOLORADJUSTMENT\n"); ASSERT(m_pRenderer); #ifndef SC_RENDERER_CAN_DOROP SCPlayRecord(); // for ROP (just in case) #endif // "The color adjustment values are used to adjust the input color of the source bitmap // for calls to the StretchBlt and StretchDIBits functions when HALFTONE mode is set." // But it's NT specific. m_pRenderer->SCSetColorAsjustment(&((EMRSETCOLORADJUSTMENT*)m_pRecord)->ColorAdjustment); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSETTEXTCOLOR() { // TRACE0("**EMR_SETTEXTCOLOR\n"); ASSERT(m_pRenderer); m_pRenderer->SCSetTextColor(((EMRSETTEXTCOLOR*)m_pRecord)->crColor); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSETBKCOLOR() { // TRACE0("**EMR_SETBKCOLOR\n"); ASSERT(m_pRenderer); m_pRenderer->SCSetBkColor(((EMRSETBKCOLOR*)m_pRecord)->crColor); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfOFFSETCLIPRGN() { // TRACE0("**EMR_OFFSETCLIPRGN\n"); ASSERT(m_pRenderer); m_pRenderer->SCOffsetClipRect(((EMROFFSETCLIPRGN*)m_pRecord)->ptlOffset); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfMOVETOEX() { // TRACE0("**EMR_MOVETOEX\n"); ASSERT(m_pRenderer); m_pRenderer->SCMoveToEx(((EMRMOVETOEX*)m_pRecord)->ptl); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSETMETARGN() { // TRACE0("**EMR_SETMETARGN\n"); ASSERT(m_pRenderer); m_pRenderer->SCOnSetMetaRgn(); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfEXCLUDECLIPRECT() { // TRACE0("**EMR_EXCLUDECLIPRECT\n"); ASSERT(m_pRenderer); m_pRenderer->SCExcludeClipRect(((EMREXCLUDECLIPRECT*)m_pRecord)->rclClip); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfINTERSECTCLIPRECT() { // TRACE0("**EMR_INTERSECTCLIPRECT\n"); ASSERT(m_pRenderer); m_pRenderer->SCIntersectClipRect(((EMRINTERSECTCLIPRECT*)m_pRecord)->rclClip); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSCALEVIEWPORTEXTEX() { // TRACE0("**EMR_SCALEVIEWPORTEXTEX\n"); ASSERT(m_pRenderer); #ifndef SC_RENDERER_CAN_DOROP SCPlayRecord(); // required for ROP management #endif EMRSCALEVIEWPORTEXTEX *pRec = (EMRSCALEVIEWPORTEXTEX*)m_pRecord; m_pRenderer->SCScaleViewport(pRec->xNum, pRec->xDenom, pRec->yNum, pRec->yDenom); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSCALEWINDOWEXTEX() { // TRACE0("**EMR_SCALEWINDOWEXTEX\n"); ASSERT(m_pRenderer); #ifndef SC_RENDERER_CAN_DOROP SCPlayRecord(); // required for ROP management #endif EMRSCALEWINDOWEXTEX *pRec = (EMRSCALEWINDOWEXTEX*)m_pRecord; m_pRenderer->SCScaleWindow(pRec->xNum, pRec->xDenom, pRec->yNum, pRec->yDenom); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSAVEDC() { // TRACE0("**EMR_SAVEDC\n"); ASSERT(m_pRenderer); SCPlayRecord(); m_pRenderer->SCOnDCSaved(); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfRESTOREDC() { // TRACE0("**EMR_RESTOREDC\n"); ASSERT(m_pRenderer); SCPlayRecord(); // Be careful : sometimes we get bad values from the record. // Some documents contain values like 30, // though there is only one DC state on the stack m_pRenderer->SCOnDCRestored(((EMRRESTOREDC*)m_pRecord)->iRelative); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSETWORLDTRANSFORM() { // TRACE0("**EMR_SETWORLDTRANSFORM\n"); ASSERT(m_pRenderer); #ifndef SC_RENDERER_CAN_DOROP SCPlayRecord(); // required for ROP management #endif m_pRenderer->SCSetWorldTransform(((EMRSETWORLDTRANSFORM*)m_pRecord)->xform); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfMODIFYWORLDTRANSFORM() { // TRACE0("**EMR_MODIFYWORLDTRANSFORM\n"); ASSERT(m_pRenderer); #ifndef SC_RENDERER_CAN_DOROP SCPlayRecord(); // required for ROP management #endif m_pRenderer->SCModifyWorldTransform(((EMRMODIFYWORLDTRANSFORM*)m_pRecord)->xform, ((EMRMODIFYWORLDTRANSFORM*)m_pRecord)->iMode); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSELECTOBJECT() { // TRACE0("**EMR_SELECTOBJECT\n"); ASSERT(m_pRenderer); // First, play the record to realize GDI objects SCPlayRecord(); // Then extract objects characteristics EMRSELECTOBJECT *pRec = (EMRSELECTOBJECT*)m_pRecord; HGDIOBJ hGdiObj; // Is the high order bit set? if (pRec->ihObject & 0x80000000) { // High order bit is set - its a stock object // Strip the high bit to get the index DWORD dwIndex = pRec->ihObject & 0x7fffffff; // Pass the index to GetStockObject() hGdiObj = GetStockObject( dwIndex ); } else // High order bit isn't set - not a stock object hGdiObj = (HGDIOBJ)m_lpEnumHandleTable->objectHandle[pRec->ihObject]; long lType = GetObjectType(hGdiObj); switch(lType) { case OBJ_EXTPEN: m_pRenderer->SCOnChangeExtPen((HPEN)hGdiObj); break; case OBJ_PEN: m_pRenderer->SCOnChangePen((HPEN)hGdiObj); break; case OBJ_BRUSH: m_pRenderer->SCOnChangeBrush((HBRUSH)hGdiObj); break; case OBJ_FONT: m_pRenderer->SCOnChangeFont((HFONT)hGdiObj); break; //case OBJ_PAL: // unlikely to occur (The SelectObject function does not work with palettes) //m_pRenderer->SCOnChangePalette((HPALETTE)hGdiObj); //break; } return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfCREATEPEN() { // TRACE0("**EMR_CREATEPEN\n"); ASSERT(m_pRenderer); SCPlayRecord(); // Object creation: do nothing // EMRCREATEPEN *pRec = (EMRCREATEPEN*)m_pRecord; return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfCREATEBRUSHINDIRECT() { // TRACE0("**EMR_CREATEBRUSHINDIRECT\n"); ASSERT(m_pRenderer); // Note: due to dithering, Windows may change BS_SOLID in BS_PATTERN SCPlayRecord(); // Object creation: do nothing // EMRCREATEBRUSHINDIRECT *pRec = (EMRCREATEBRUSHINDIRECT*)m_pRecord; return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfDELETEOBJECT() { // TRACE0("**EMR_DELETEOBJECT\n"); ASSERT(m_pRenderer); SCPlayRecord(); // Object deletion: do nothing // EMRDELETEOBJECT *pRec = (EMRDELETEOBJECT*)m_pRecord; return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfANGLEARC() { // TRACE0("**EMR_ANGLEARC\n"); ASSERT(m_pRenderer); EMRANGLEARC *pRec = (EMRANGLEARC*)m_pRecord; m_pRenderer->SCDrawAngleArc((LPPOINT)&pRec->ptlCenter, pRec->nRadius, pRec->eStartAngle, pRec->eSweepAngle); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfELLIPSE() { // TRACE0("**EMR_ELLIPSE\n"); ASSERT(m_pRenderer); m_pRenderer->SCDrawEllipse((LPCRECT)&((EMRELLIPSE*)m_pRecord)->rclBox); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfRECTANGLE() { // TRACE0("**EMR_RECTANGLE\n"); ASSERT(m_pRenderer); m_pRenderer->SCDrawRectangle((LPCRECT)&((EMRRECTANGLE*)m_pRecord)->rclBox); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfROUNDRECT() { // TRACE0("**EMR_ROUNDRECT\n"); ASSERT(m_pRenderer); m_pRenderer->SCDrawRoundRectangle((LPCRECT)&((EMRROUNDRECT*)m_pRecord)->rclBox, ((EMRROUNDRECT*)m_pRecord)->szlCorner); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfARC() { // TRACE0("**EMR_ARC\n"); ASSERT(m_pRenderer); m_pRenderer->SCDrawArc(&((EMRARC*)m_pRecord)->rclBox, &((EMRARC*)m_pRecord)->ptlStart, &((EMRARC*)m_pRecord)->ptlEnd); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfCHORD() { // TRACE0("**EMR_CHORD\n"); ASSERT(m_pRenderer); m_pRenderer->SCDrawChord(&((EMRCHORD*)m_pRecord)->rclBox, &((EMRCHORD*)m_pRecord)->ptlStart, &((EMRCHORD*)m_pRecord)->ptlEnd); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfPIE() { // TRACE0("**EMR_PIE\n"); ASSERT(m_pRenderer); m_pRenderer->SCDrawPie(&((EMRPIE*)m_pRecord)->rclBox, &((EMRPIE*)m_pRecord)->ptlStart, &((EMRPIE*)m_pRecord)->ptlEnd); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSELECTPALETTE() { // TRACE0("**EMR_SELECTPALETTE\n"); ASSERT(m_pRenderer); SCPlayRecord(); m_pRenderer->SCOnChangePalette((HPALETTE)((EMRSELECTPALETTE*)m_pRecord)->ihPal); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfCREATEPALETTE() { // TRACE0("**EMR_CREATEPALETTE\n"); ASSERT(m_pRenderer); SCPlayRecord(); // Object creation: do nothing // EMRCREATEPALETTE *pRec = (EMRCREATEPALETTE*)m_pRecord; return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSETPALETTEENTRIES() { // TRACE0("**EMR_SETPALETTEENTRIES\n"); ASSERT(m_pRenderer); SCPlayRecord(); // Object creation: do nothing // EMRSETPALETTEENTRIES *pRec = (EMRSETPALETTEENTRIES*)m_pRecord; return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfRESIZEPALETTE() { // TRACE0("**EMR_RESIZEPALETTE\n"); ASSERT(m_pRenderer); SCPlayRecord(); // Object creation: do nothing // EMRRESIZEPALETTE *pRec = (EMRRESIZEPALETTE*)m_pRecord; return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfREALIZEPALETTE() { // TRACE0("**EMR_REALIZEPALETTE\n"); ASSERT(m_pRenderer); SCPlayRecord(); // Object creation: do nothing // EMRREALIZEPALETTE *pRec = (EMRREALIZEPALETTE*)m_pRecord; return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfEXTFLOODFILL() { // TRACE0("**EMR_EXTFLOODFILL\n"); ASSERT(m_pRenderer); m_pRenderer->SCFloodFill(((EMREXTFLOODFILL*)m_pRecord)->ptlStart, ((EMREXTFLOODFILL*)m_pRecord)->crColor, ((EMREXTFLOODFILL*)m_pRecord)->iMode); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfLINETO() { // TRACE0("**EMR_LINETO\n"); ASSERT(m_pRenderer); m_pRenderer->SCDrawLinesTo((LPPOINT)&((EMRLINETO*)m_pRecord)->ptl, 1); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfARCTO() { // TRACE0("**EMR_ARCTO\n"); ASSERT(m_pRenderer); m_pRenderer->SCDrawArcTo(&((EMRARCTO*)m_pRecord)->rclBox, &((EMRARCTO*)m_pRecord)->ptlStart, &((EMRARCTO*)m_pRecord)->ptlEnd); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfPOLYDRAW() { // TRACE0("**EMR_POLYDRAW\n"); ASSERT(m_pRenderer); EMRPOLYDRAW *pRec = (EMRPOLYDRAW*)m_pRecord; BYTE* pTypes = (BYTE*)((POINTL*)pRec->aptl + pRec->cptl); m_pRenderer->SCDrawPolyDraw((POINT*)pRec->aptl, pRec->cptl, pTypes); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSETARCDIRECTION() { // TRACE0("**EMR_SETARCDIRECTION\n"); ASSERT(m_pRenderer); m_pRenderer->SCSetArcDirection(((EMRSETARCDIRECTION*)m_pRecord)->iArcDirection); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSETMITERLIMIT() { // TRACE0("**EMR_SETMITERLIMIT\n"); ASSERT(m_pRenderer); m_pRenderer->SCSetMiterLimit(((EMRSETMITERLIMIT*)m_pRecord)->eMiterLimit); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfBEGINPATH() { // TRACE0("**EMR_BEGINPATH\n"); ASSERT(m_pRenderer); //EMRBEGINPATH *pRec = (EMRBEGINPATH*)m_pRecord; m_pRenderer->SCBeginPath(); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfENDPATH() { // TRACE0("**EMR_ENDPATH\n"); ASSERT(m_pRenderer); //EMRENDPATH *pRec = (EMRENDPATH*)m_pRecord; m_pRenderer->SCEndPath(); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfCLOSEFIGURE() { // TRACE0("**EMR_CLOSEFIGURE\n"); ASSERT(m_pRenderer); //EMRCLOSEFIGURE *pRec = (EMRCLOSEFIGURE*)m_pRecord; m_pRenderer->SCCloseFigure(); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfFILLPATH() { // TRACE0("**EMR_FILLPATH\n"); ASSERT(m_pRenderer); //EMRFILLPATH *pRec = (EMRFILLPATH*)m_pRecord; // Note: Don't know what the rclBounds is doing in the record m_pRenderer->SCApplyPath(SC_PATH_FILL); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSTROKEANDFILLPATH() { // TRACE0("**EMR_STROKEANDFILLPATH\n"); ASSERT(m_pRenderer); //EMRSTROKEANDFILLPATH *pRec = (EMRSTROKEANDFILLPATH*)m_pRecord; // Note: Don't know what the rclBounds is doing in the record m_pRenderer->SCApplyPath(SC_PATH_STROKEANDFILL); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSTROKEPATH() { // TRACE0("**EMR_STROKEPATH\n"); ASSERT(m_pRenderer); //EMRSTROKEPATH *pRec = (EMRSTROKEPATH*)m_pRecord; // Note: Don't know what the rclBounds is doing in the record m_pRenderer->SCApplyPath(SC_PATH_STROKE); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfFLATTENPATH() { // TRACE0("**EMR_FLATTENPATH\n"); ASSERT(m_pRenderer); //EMRFLATTENPATH *pRec = (EMRFLATTENPATH*)m_pRecord; m_pRenderer->SCFlattenPath(); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfWIDENPATH() { // TRACE0("**EMR_WIDENPATH\n"); ASSERT(m_pRenderer); //EMRWIDENPATH *pRec = (EMRWIDENPATH*)m_pRecord; m_pRenderer->SCWidenPath(); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSELECTCLIPPATH() { // TRACE0("**EMR_SELECTCLIPPATH\n"); ASSERT(m_pRenderer); m_pRenderer->SCApplyPath(SC_PATH_CLIP, ((EMRSELECTCLIPPATH*)m_pRecord)->iMode); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfABORTPATH() { // TRACE0("**EMR_ABORTPATH\n"); ASSERT(m_pRenderer); //EMRABORTPATH *pRec = (EMRABORTPATH*)m_pRecord; m_pRenderer->SCAbortPath(); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfGDICOMMENT() { // TRACE0("**EMR_GDICOMMENT\n"); ASSERT(m_pRenderer); #pragma message( __FILE__ "(894): TODO: Recurse parser on embedded WMF? ") #if 0 EMRGDICOMMENT *pRec = (EMRGDICOMMENT*)m_pRecord; DWORD* pDW = (DWORD*)pRec->Data; if (GDICOMMENT_IDENTIFIER==*pDW) { pDW++; switch(*pDW) { case GDICOMMENT_WINDOWS_METAFILE: // embedded WMF // TODO: break; case GDICOMMENT_MULTIFORMATS: // embedded formats // TODO: break; } } #endif SCPlayRecord(); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfFILLRGN() { // TRACE0("**EMR_FILLRGN\n"); ASSERT(m_pRenderer); m_pRenderer->SCFillRgn((HBRUSH)m_lpEnumHandleTable->objectHandle[((EMRFILLRGN*)m_pRecord)->ihBrush], ((EMRFILLRGN*)m_pRecord)->RgnData, ((EMRFILLRGN*)m_pRecord)->cbRgnData); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfFRAMERGN() { // TRACE0("**EMR_FRAMERGN\n"); ASSERT(m_pRenderer); m_pRenderer->SCFrameRgn((HBRUSH)m_lpEnumHandleTable->objectHandle[((EMRFRAMERGN*)m_pRecord)->ihBrush], ((EMRFRAMERGN*)m_pRecord)->szlStroke, ((EMRFRAMERGN*)m_pRecord)->RgnData, ((EMRFRAMERGN*)m_pRecord)->cbRgnData); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfINVERTRGN() { // TRACE0("**EMR_INVERTRGN\n"); ASSERT(m_pRenderer); m_pRenderer->SCInvertRgn(((EMRINVERTRGN*)m_pRecord)->RgnData, ((EMRINVERTRGN*)m_pRecord)->cbRgnData); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfPAINTRGN() { // TRACE0("**EMR_PAINTRGN\n"); ASSERT(m_pRenderer); m_pRenderer->SCPaintRgn(((EMRPAINTRGN*)m_pRecord)->RgnData, ((EMRPAINTRGN*)m_pRecord)->cbRgnData); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfEXTSELECTCLIPRGN() { // TRACE0("**EMR_EXTSELECTCLIPRGN\n"); ASSERT(m_pRenderer); m_pRenderer->SCSelectClipRgn(((EMREXTSELECTCLIPRGN*)m_pRecord)->RgnData, ((EMREXTSELECTCLIPRGN*)m_pRecord)->cbRgnData, ((EMREXTSELECTCLIPRGN*)m_pRecord)->iMode); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfBITBLT() { // TRACE0("**EMR_BITBLT\n"); ASSERT(m_pRenderer); EMRBITBLT *pRec = (EMRBITBLT*)m_pRecord; // Destination CRect RcDest(pRec->xDest, pRec->yDest, pRec->xDest + pRec->cxDest, pRec->yDest + pRec->cyDest); // Check if there is a bitmap if (pRec->offBmiSrc && pRec->offBitsSrc) { BITMAPINFO *pBmi = (BITMAPINFO *) ((BYTE *)pRec + pRec->offBmiSrc); BYTE *pBits = (BYTE *) ((BYTE *) pRec + pRec->offBitsSrc); // Source and Destination have same size for BitBlt function CRect RcSrc(pRec->xSrc, pRec->ySrc, pRec->xSrc + pRec->cxDest, pRec->ySrc + pRec->cyDest); m_pRenderer->SCDrawImage(&RcDest, &RcSrc, pBits, pBmi, pRec->iUsageSrc, pRec->dwRop, &pRec->xformSrc); } else m_pRenderer->SCPatBlt(&RcDest, pRec->dwRop, &pRec->xformSrc); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSTRETCHBLT() { // TRACE0("**EMR_STRETCHBLT\n"); ASSERT(m_pRenderer); EMRSTRETCHBLT *pRec = (EMRSTRETCHBLT*)m_pRecord; // Destination CRect RcDest(pRec->xDest, pRec->yDest, pRec->xDest + pRec->cxDest, pRec->yDest + pRec->cyDest); // Check if there is a bitmap if (pRec->offBmiSrc && pRec->offBitsSrc) { BITMAPINFO *pBmi = (BITMAPINFO *) ((BYTE *)pRec + pRec->offBmiSrc); BYTE *pBits = (BYTE *) ((BYTE *) pRec + pRec->offBitsSrc); // Source CRect RcSrc(pRec->xSrc, pRec->ySrc, pRec->xSrc + pRec->cxSrc, pRec->ySrc + pRec->cySrc); m_pRenderer->SCDrawImage(&RcDest, &RcSrc, pBits, pBmi, pRec->iUsageSrc, pRec->dwRop, &pRec->xformSrc); } else m_pRenderer->SCPatBlt(&RcDest, pRec->dwRop, &pRec->xformSrc); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfMASKBLT() { // TRACE0("**EMR_MASKBLT\n"); ASSERT(m_pRenderer); EMRMASKBLT *pRec = (EMRMASKBLT*)m_pRecord; // Destination CRect RcDest(pRec->xDest, pRec->yDest, pRec->xDest + pRec->cxDest, pRec->yDest + pRec->cyDest); // Check if there is a bitmap if (pRec->offBmiSrc && pRec->offBitsSrc) { // the source bitmap BITMAPINFO *pBmi = (BITMAPINFO *) ((BYTE *)pRec + pRec->offBmiSrc); BYTE *pBits = (BYTE *) ((BYTE *) pRec + pRec->offBitsSrc); // the mask bitmap is optional BITMAPINFO *pBmiMask = NULL; BYTE *pBitsMask = NULL; if (pRec->offBmiMask && pRec->offBitsMask) { pBmiMask = (BITMAPINFO *)((BYTE *)pRec + pRec->offBmiMask); pBitsMask = (BYTE *)((BYTE *)pRec + pRec->offBitsMask); } // Source equals dest in dimensions CRect RcSrc(pRec->xSrc, pRec->ySrc, pRec->xSrc + pRec->cxDest, pRec->ySrc + pRec->cyDest); m_pRenderer->SCDrawImageMsk(&RcDest, &RcSrc, pBits, pBmi, pRec->iUsageSrc, pRec->dwRop, &pRec->xformSrc, pRec->crBkColorSrc, pRec->xMask, pRec->yMask, pBitsMask, pBmiMask, pRec->iUsageMask); } else m_pRenderer->SCPatBlt(&RcDest, pRec->dwRop, &pRec->xformSrc); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfPLGBLT() { // TRACE0("**EMR_PLGBLT\n"); ASSERT(m_pRenderer); EMRPLGBLT *pRec = (EMRPLGBLT*)m_pRecord; ASSERT(pRec->offBmiSrc && pRec->offBitsSrc); if (pRec->offBmiSrc && pRec->offBitsSrc) { // the source bitmap BITMAPINFO *pBmi = (BITMAPINFO *)((BYTE *)pRec + pRec->offBmiSrc); BYTE *pBits = (BYTE *)((BYTE *)pRec + pRec->offBitsSrc); // the mask bitmap is optional BITMAPINFO *pBmiMask = NULL; BYTE *pBitsMask = NULL; if (pRec->offBmiMask && pRec->offBitsMask) { pBmiMask = (BITMAPINFO *)((BYTE *)pRec + pRec->offBmiMask); pBitsMask = (BYTE *)((BYTE *)pRec + pRec->offBitsMask); } // Source CRect RcSrc(pRec->xSrc, pRec->ySrc, pRec->xSrc + pRec->cxSrc, pRec->ySrc + pRec->cySrc); m_pRenderer->SCDrawImagePlg(pRec->aptlDest, &RcSrc, pBits, pBmi, pRec->iUsageSrc, &pRec->xformSrc, pRec->crBkColorSrc, pRec->xMask, pRec->yMask, pBitsMask, pBmiMask, pRec->iUsageMask); } return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSETDIBITSTODEVICE() { // TRACE0("**EMR_SETDIBITSTODEVICE\n"); ASSERT(m_pRenderer); EMRSETDIBITSTODEVICE *pRec = (EMRSETDIBITSTODEVICE*)m_pRecord; // Destination CRect RcDest(pRec->xDest, pRec->yDest, pRec->xDest + pRec->cxSrc, pRec->yDest + pRec->cySrc); // Check if there is a bitmap if (pRec->offBmiSrc && pRec->offBitsSrc) { BITMAPINFO *pBmi = (BITMAPINFO *) ((BYTE *)pRec + pRec->offBmiSrc); BYTE *pBits = (BYTE *) ((BYTE *) pRec + pRec->offBitsSrc); // Source CRect RcSrc(pRec->xSrc, pRec->ySrc, pRec->xSrc + pRec->cxSrc, pRec->ySrc + pRec->cySrc); m_pRenderer->SCDrawImage(&RcDest, &RcSrc, pBits, pBmi, pRec->iUsageSrc, SRCCOPY); } else m_pRenderer->SCPatBlt(&RcDest, SRCCOPY); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSTRETCHDIBITS() { ASSERT(m_pRenderer); // TRACE0("**EMR_STRETCHDIBITS\n"); EMRSTRETCHDIBITS *pRec = (EMRSTRETCHDIBITS*)m_pRecord; // Destination CRect RcDest(pRec->xDest, pRec->yDest, pRec->xDest + pRec->cxDest, pRec->yDest + pRec->cyDest); // Check if there is a bitmap if (pRec->offBmiSrc && pRec->offBitsSrc) { BITMAPINFO *pBmi = (BITMAPINFO *) ((BYTE *)pRec + pRec->offBmiSrc); BYTE *pBits = (BYTE *) ((BYTE *) pRec + pRec->offBitsSrc); // Source CRect RcSrc(pRec->xSrc, pRec->ySrc, pRec->xSrc + pRec->cxSrc, pRec->ySrc + pRec->cySrc); m_pRenderer->SCDrawImage(&RcDest, &RcSrc, pBits, pBmi, pRec->iUsageSrc, pRec->dwRop); } else m_pRenderer->SCPatBlt(&RcDest, pRec->dwRop); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfEXTCREATEFONTINDIRECTW() { // TRACE0("**EMR_EXTCREATEFONTINDIRECTW\n"); ASSERT(m_pRenderer); // Play the record on the DC, in order to get information about the physical font, // which is the font really used by the DC. #if 0 // Raster and vector fonts should be replaced by substitutes. // Example of early font substitution. // This is cleaner than late substitution (SCTTFontFromLOGFONT in SCGdiplusUtils.cpp); // but it penalizes good TT fonts // (memory allocations and string comparisons) EMREXTCREATEFONTINDIRECTW *pSubs = (EMREXTCREATEFONTINDIRECTW *)SCCloneRecord(); if (pSubs) { LOGFONTW& rLogFont = pSubs->elfw.elfLogFont; DWORD dwFamily = SCFontFamilyApproximantW((WCHAR*)rLogFont.lfFaceName); if (FF_DONTCARE!=dwFamily) { rLogFont.lfPitchAndFamily |= dwFamily; rLogFont.lfOutPrecision = OUT_TT_ONLY_PRECIS; } SCPlayRecordAndFree(pSubs); } else SCPlayRecord(); #else SCPlayRecord(); #endif return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfEXTTEXTOUTA() { // TRACE0("**EMR_EXTTEXTOUTA or **EMR_EXTTEXTOUTW\n"); ASSERT(m_pRenderer); SC_BRKRESULT error(SC_BRK_NOERROR); // the structure EMREXTTEXTOUTA is same as EMREXTTEXTOUTW EMREXTTEXTOUTA *pRec = (EMREXTTEXTOUTA*)m_pRecord; // get the EMRTEXT EMRTEXT *pTextRec = &(pRec->emrtext); // number of characters INT iNbChars = pTextRec->nChars; if (iNbChars<=0) { // We don't know the behavior of ExtTextOut: // - if number of characters is 0 // - if, moreover, TA_UPDATECP is set in the DC #if 0 // if required, play the record SCPlayRecord(); #endif return 0; } UINT uiOptions = pTextRec->fOptions; // we might have to alter it // Build the string LPWSTR pwStr = NULL; if (pRec->emr.iType == EMR_EXTTEXTOUTW) { // The string is in unicode -> we let it as is. // Offset is from the beginning of the struct and is in bytes. // // Get the unicode string pwStr = (LPWSTR) ((BYTE *)pRec + pTextRec->offString); #if 0 // TODO: // Translate glyph indices to code points when the rasterizer does not // support string measurement for glyph indices. if ((uiOptions & ETO_GLYPH_INDEX) && (!m_pRenderer->SCCanMeasureGlyphs()) { int iRes = SCUnicodeCharsFromGlyphs(m_hPlayDC, pString, iNbChars); if (iRes) uiOptions &= ~ETO_GLYPH_INDEX; } #endif } else { // The string is single-byte encoded. // Get adress of the string then construct the string. LPSTR pString = (char *)pRec + pTextRec->offString; pwStr = new wchar_t[iNbChars+1]; if (pwStr) {// We will use UNICODE strings exclusively pwStr[iNbChars] = 0; int iNum = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pString, iNbChars, pwStr, iNbChars+1); ASSERT(iNum==iNbChars); } } ASSERT(pwStr); // Get intercharacter spacing array. // Be careful ! there are cases where OffDx==0. DWORD OffDx = pTextRec->offDx; INT *lpDx = (INT*)((BYTE*)pRec + OffDx); if (0==OffDx) { // If the lpDx parameter is NULL, the ExtTextOut function uses the default // spacing between characters. So we do. // // Compute intercharacter spacing, based on each character width. lpDx = new INT[iNbChars]; BOOL bOk = SCGetTextCharWidthsW(m_hPlayDC, pwStr, iNbChars, lpDx); ASSERT(bOk); } else { // else use distances between origins of adjacent character cells as passed to ExtTextOut. // except that, sometimes, the last character is given a spacing of 0, which is // not good for us if this character has a non-null width. if (0==lpDx[iNbChars-1]) { INT* pInts = new INT[iNbChars]; memmove(pInts, lpDx, iNbChars*sizeof(INT)); // compute only the last character's width BOOL bOk = SCGetTextCharWidthsW(m_hPlayDC, pwStr+iNbChars-1, 1, pInts+iNbChars-1); ASSERT(bOk); lpDx = pInts; OffDx = 0; // for cleanup //at this point, 0 is accepted //ASSERT(lpDx[iNbChars-1]); } } #if 0 // This thing is not accurate. We prefer to let the rasterizer use its computed rectangle // when no opaquing rectangle is supplied CRect rcText = (LPCRECT)&pTextRec->rcl; if (rcText.IsRectEmpty()) { rcText.CopyRect((LPCRECT)&pRec->rclBounds); DPtoLP(m_hPlayDC, (LPPOINT)&rcText, 2); } if (GM_COMPATIBLE==pRec->iGraphicsMode) m_pRenderer->SCDrawText(pTextRec->ptlReference.x, pTextRec->ptlReference.y, uiOptions, (LPCRECT)&rcText, pwStr, iNbChars, lpDx, pRec->exScale, pRec->eyScale); else m_pRenderer->SCDrawText(pTextRec->ptlReference.x, pTextRec->ptlReference.y, uiOptions, (LPCRECT)&rcText, pwStr, iNbChars, lpDx, 1, 1); #else if (GM_COMPATIBLE==pRec->iGraphicsMode) m_pRenderer->SCDrawText(pTextRec->ptlReference.x, pTextRec->ptlReference.y, uiOptions, (LPCRECT)&pTextRec->rcl, pwStr, iNbChars, lpDx, pRec->exScale, pRec->eyScale); else m_pRenderer->SCDrawText(pTextRec->ptlReference.x, pTextRec->ptlReference.y, uiOptions, (LPCRECT)&pTextRec->rcl, pwStr, iNbChars, lpDx, 1, 1); #endif // Clean up if (pRec->emr.iType == EMR_EXTTEXTOUTA) delete [] pwStr; if (0==OffDx) delete [] lpDx; return error; } ////////////////////////////////////////////////////////////////////////////////////// // It is unlikely that SCEmfTextoutA/SCEmfTextoutW are called. So I prefer to let // them separated (with duplicated code). See OnEmfTextoutA for documentation SC_BRKRESULT CSCEMFgdiParser::SCEmfTextoutA(EMREXTTEXTOUTA* pRec, EMRTEXT* pTextRec) { INT iNbChars = pTextRec->nChars; if (iNbChars<=0) return SC_BRK_NOERROR; // Get adress of the string then construct the widestring. LPWSTR pwStr = new wchar_t[iNbChars + 1]; if (pwStr) {// We will use UNICODE strings exclusively pwStr[iNbChars] = 0; int iNum = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)((char *)pRec + pTextRec->offString), iNbChars, pwStr, iNbChars + 1); ASSERT(iNum==iNbChars); SCFinishTextout(pRec, pTextRec, pwStr, pTextRec->fOptions); // Clean up delete [] pwStr; } return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::SCEmfTextoutW(EMREXTTEXTOUTW* pRec, EMRTEXT* pTextRec) { INT iNbChars = pTextRec->nChars; if (iNbChars<=0) return SC_BRK_NOERROR; UINT uiOptions = pTextRec->fOptions; // we might have to alter it // Get the unicode string LPWSTR pwStr = (LPWSTR) ((BYTE *)pRec + pTextRec->offString); #if 0 ASSERT(m_pRenderer); // TODO: // Translate glyph indices to code points when the rasterizer does not // support string measurement for glyph indices. if ((uiOptions & ETO_GLYPH_INDEX) && (!m_pRenderer->SCCanMeasureGlyphs()) { int iRes = SCUnicodeCharsFromGlyphs(m_hPlayDC, pwStr, iNbChars); if (iRes) uiOptions &= ~ETO_GLYPH_INDEX; } #endif SCFinishTextout(pRec, pTextRec, pwStr, uiOptions); return SC_BRK_NOERROR; } void CSCEMFgdiParser::SCFinishTextout(EMREXTTEXTOUTA* pRec, EMRTEXT* pTextRec, LPWSTR pwStr, UINT uiOptions) { ASSERT(m_pRenderer); INT iNbChars = pTextRec->nChars; // Get intercharacter spacing array. DWORD OffDx = pTextRec->offDx; INT *lpDx = (INT*)((BYTE*)pRec + OffDx); if (0==OffDx) { // Compute intercharacter spacing, based on each character width. lpDx = new INT[iNbChars]; BOOL bOk = SCGetTextCharWidthsW(m_hPlayDC, pwStr, iNbChars, lpDx); ASSERT(bOk); } else { // else use distances between origins of adjacent character cells as passed to ExtTextOut. // except that, sometimes, the last character is given a spacing of 0, which is not good for us. if (0==lpDx[iNbChars-1]) { INT* pInts = new INT[iNbChars]; memmove(pInts, lpDx, iNbChars*sizeof(INT)); // compute only the last character's width BOOL bOk = SCGetTextCharWidthsW(m_hPlayDC, pwStr+iNbChars-1, 1, pInts+iNbChars-1); ASSERT(bOk); lpDx = pInts; OffDx = 0; // for cleanup ASSERT(lpDx[iNbChars-1]); } } if (GM_COMPATIBLE==pRec->iGraphicsMode) m_pRenderer->SCDrawText(pTextRec->ptlReference.x, pTextRec->ptlReference.y, uiOptions, (LPCRECT)&pTextRec->rcl, pwStr, iNbChars, lpDx, pRec->exScale, pRec->eyScale); else m_pRenderer->SCDrawText(pTextRec->ptlReference.x, pTextRec->ptlReference.y, uiOptions, (LPCRECT)&pTextRec->rcl, pwStr, iNbChars, lpDx, 1, 1); // Clean up if (0==OffDx) delete [] lpDx; } /////////////////////////////////////////////////////////////////////////////////////////// SC_BRKRESULT CSCEMFgdiParser::OnEmfEXTTEXTOUTW() { // TRACE0("**EMR_EXTTEXTOUTW\n"); //EMREXTTEXTOUTW *pRec = (EMREXTTEXTOUTW*)m_pRecord; // pass the record to return OnEmfEXTTEXTOUTA(); } SC_BRKRESULT CSCEMFgdiParser::OnEmfPOLYBEZIER16() { // TRACE0("**EMR_POLYBEZIER16\n"); ASSERT(m_pRenderer); m_pRenderer->SCDrawBezierS(((EMRPOLYBEZIER16*)m_pRecord)->apts, ((EMRPOLYBEZIER16*)m_pRecord)->cpts); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfPOLYGON16() { // TRACE0("**EMR_POLYGON16\n"); ASSERT(m_pRenderer); m_pRenderer->SCDrawPolygonS(((EMRPOLYGON16*)m_pRecord)->apts, ((EMRPOLYGON16*)m_pRecord)->cpts); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfPOLYLINE16() { // TRACE0("**EMR_POLYLINE16\n"); ASSERT(m_pRenderer); m_pRenderer->SCDrawLinesS(((EMRPOLYLINE16*)m_pRecord)->apts, ((EMRPOLYLINE16*)m_pRecord)->cpts); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfPOLYBEZIERTO16() { // TRACE0("**EMR_POLYBEZIERTO16\n"); ASSERT(m_pRenderer); m_pRenderer->SCDrawBezierToS(((EMRPOLYBEZIERTO16*)m_pRecord)->apts, ((EMRPOLYBEZIERTO16*)m_pRecord)->cpts); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfPOLYLINETO16() { // TRACE0("**EMR_POLYLINETO16\n"); ASSERT(m_pRenderer); m_pRenderer->SCDrawLinesToS(((EMRPOLYLINETO16*)m_pRecord)->apts, ((EMRPOLYLINETO16*)m_pRecord)->cpts); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfPOLYPOLYLINE16() { // TRACE0("**EMR_POLYPOLYLINE16\n"); ASSERT(m_pRenderer); EMRPOLYPOLYLINE16 *pRec = (EMRPOLYPOLYLINE16*)m_pRecord; LPPOINTS pPts = (LPPOINTS)((DWORD*)pRec->aPolyCounts + pRec->nPolys); m_pRenderer->SCDrawPolyPolylineS(pPts, pRec->cpts, (DWORD*)pRec->aPolyCounts, pRec->nPolys); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfPOLYPOLYGON16() { // TRACE0("**EMR_POLYPOLYGON16\n"); ASSERT(m_pRenderer); EMRPOLYPOLYGON16 *pRec = (EMRPOLYPOLYGON16*)m_pRecord; LPPOINTS pPts = (LPPOINTS)((DWORD*)pRec->aPolyCounts + pRec->nPolys); m_pRenderer->SCDrawPolyPolygonS(pPts, pRec->cpts, (DWORD*)pRec->aPolyCounts, pRec->nPolys); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfPOLYDRAW16() { // TRACE0("**EMR_POLYDRAW16\n"); ASSERT(m_pRenderer); EMRPOLYDRAW16 *pRec = (EMRPOLYDRAW16*)m_pRecord; BYTE* pTypes = (BYTE*)((POINTS*)pRec->apts + pRec->cpts); m_pRenderer->SCDrawPolyDrawS(pRec->apts, pRec->cpts, pTypes); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfCREATEMONOBRUSH() { // TRACE0("**EMR_CREATEMONOBRUSH\n"); ASSERT(m_pRenderer); EMRCREATEMONOBRUSH *pRec = (EMRCREATEMONOBRUSH*)m_pRecord; // SCPlayRecord() won't work: the brush will reference a deleted bitmap (XP specific bug?). // See comments in the final block. SCPlayRecord(); #ifndef DIB_PAL_INDICES #define DIB_PAL_INDICES 2 #endif ASSERT(DIB_PAL_INDICES==pRec->iUsage); // DIB_PAL_INDICES management. Special case: the DIB has no color table. BITMAPINFO *pBmi = (BITMAPINFO *) ((BYTE *)pRec + pRec->offBmi); DWORD *pBitsDW = (DWORD *) ((BYTE *) pRec + pRec->offBits); // Attach a monochrome palette to the DIB specification, // and create a device-dependent bitmap HBITMAP hBm = NULL; DWORD dwSize = pBmi->bmiHeader.biSize + 2*sizeof(RGBQUAD); BITMAPINFO* pBmi2 = (BITMAPINFO*) new BYTE[dwSize]; memmove(pBmi2, pBmi, dwSize); HDC hMonoDC = CreateCompatibleDC(m_hPlayDC); // must be monochrome ASSERT(hMonoDC); SCFillMonochromePalette(hMonoDC, (PPALETTEENTRY)pBmi2->bmiColors); // May create resource leak, as we don't call DeleteObject on hBm (see comments in the final block) hBm = CreateDIBitmap(hMonoDC, &pBmi2->bmiHeader, CBM_INIT, pBitsDW, pBmi2, DIB_RGB_COLORS); DeleteDC(hMonoDC); delete [] (BYTE*)pBmi2; ASSERT(hBm); #ifdef _DEBUG {// check BITMAP bm; int iRes = GetObject(hBm, sizeof(BITMAP), &bm); ASSERT(iRes); } #endif HBRUSH hBrush = CreatePatternBrush(hBm); ASSERT(hBrush); m_lpEnumHandleTable->objectHandle[pRec->ihBrush] = hBrush; #if 0 // Don't do this normal step of the code: // DeleteObject(hBm); // It seems that XP's CreatePatternBrush does not make a copy of the given bitmap. // To prove it, activate this code, and you will see that GetObjectType // will fail on the LogBrushVerif2.lbHatch handle returned by GetObject. { // Check before delete LOGBRUSH LogBrushVerif1; ASSERT(::GetObject(hBrush, sizeof(LogBrushVerif1), &LogBrushVerif1)); ASSERT(LogBrushVerif1.lbStyle==BS_PATTERN); int iType1 = GetObjectType((HGDIOBJ)LogBrushVerif1.lbHatch); ASSERT(iType1==OBJ_BITMAP); // Suppose we delete it DeleteObject(hBm); // Check after delete LOGBRUSH LogBrushVerif2; ASSERT(::GetObject(hBrush, sizeof(LogBrushVerif2), &LogBrushVerif2)); ASSERT(LogBrushVerif2.lbStyle==BS_PATTERN); int iType2 = GetObjectType((HGDIOBJ)LogBrushVerif2.lbHatch); ASSERT(iType2==OBJ_BITMAP); // fails } #endif return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfCREATEDIBPATTERNBRUSHPT() { // TRACE0("**EMR_CREATEDIBPATTERNBRUSHPT\n"); ASSERT(m_pRenderer); #if 0 // On NT.SP5, Same problem as monobrush SCPlayRecord(); #else EMRCREATEDIBPATTERNBRUSHPT *pRec = (EMRCREATEDIBPATTERNBRUSHPT*)m_pRecord; ASSERT(DIB_PAL_COLORS==pRec->iUsage || DIB_RGB_COLORS==pRec->iUsage); BITMAPINFO *pBmi = (BITMAPINFO *) ((BYTE *)pRec + pRec->offBmi); // Note: On Windows 95 and Windows 98, "creating brushes from bitmaps or DIBs // larger than 8x8 pixels is not supported". So we should restrict the pattern to 8x8. // But what if the EMF was created on NT/2K/XP? It seems that GDI doesn't shrink the // pattern in order to render the EMF OS-independently. DWORD dwSize = pRec->cbBmi + pRec->cbBits; // should agree with: // BITMAPINFOHEADER* pBmih = &pBmi->bmiHeader; // DWORD dwSize = pBmih->biSize + // ColorTableSize(pBmih) + // ((pBmih->biSizeImage) ? pBmih->biSizeImage : // abs(pBmih->biHeight)*WIDTHBYTES(pBmih->biWidth*pBmih->biBitCount)); // May create resource leak, as we don't call GlobalFree on hMem // (in fact, this is the sole purpose of this code) HGLOBAL hMem = GlobalAlloc(GPTR, dwSize); BITMAPINFO* pBmi2 = (BITMAPINFO*)GlobalLock(hMem); memmove(pBmi2, pBmi, dwSize); HBRUSH hBrush = CreateDIBPatternBrushPt(pBmi2, pRec->iUsage); GlobalUnlock(hMem); ASSERT(hBrush); m_lpEnumHandleTable->objectHandle[pRec->ihBrush] = hBrush; #ifdef _DEBUG {// Check after play LOGBRUSH LogBrushVerif; ASSERT(::GetObject((HBRUSH)m_lpEnumHandleTable->objectHandle[pRec->ihBrush], sizeof(LogBrushVerif), &LogBrushVerif)); ASSERT(LogBrushVerif.lbStyle==BS_DIBPATTERN); } #endif #endif return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfEXTCREATEPEN() { // TRACE0("**EMR_EXTCREATEPEN\n"); ASSERT(m_pRenderer); SCPlayRecord(); // EMREXTCREATEPEN *pRec = (EMREXTCREATEPEN*)m_pRecord; return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfPOLYTEXTOUTA() { // TRACE0("**EMR_POLYTEXTOUTA\n"); ASSERT(m_pRenderer); EMRPOLYTEXTOUTA *pRec = (EMRPOLYTEXTOUTA*)m_pRecord; for (int i=0; (i<pRec->cStrings); i++) { SCEmfTextoutA((EMREXTTEXTOUTA*)pRec, &pRec->aemrtext[i]); } return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfPOLYTEXTOUTW() { // TRACE0("**EMR_POLYTEXTOUTW\n"); ASSERT(m_pRenderer); EMRPOLYTEXTOUTW *pRec = (EMRPOLYTEXTOUTW*)m_pRecord; for (int i=0; (i<pRec->cStrings); i++) { SCEmfTextoutW((EMREXTTEXTOUTW*)pRec, &pRec->aemrtext[i]); } return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSETICMMODE() { // TRACE0("**EMR_SETICMMODE\n"); ASSERT(m_pRenderer); // EMRSETICMMODE *pRec = (EMRSETICMMODE*)m_pRecord; // MSDN: see "DIBINFO.C" // TODO_EMF: Place code here to handle EMF record SCPlayRecord(); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfCREATECOLORSPACE() { // TRACE0("**EMR_CREATECOLORSPACE\n"); ASSERT(m_pRenderer); // EMRCREATECOLORSPACE *pRec = (EMRCREATECOLORSPACE*)m_pRecord; // MSDN: see "Basic ICM 2.0 Functions for Use Within a Device Context" // TODO_EMF: Place code here to handle EMF record SCPlayRecord(); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfCREATECOLORSPACEW() { // TRACE0("**EMR_CREATECOLORSPACE\n"); ASSERT(m_pRenderer); //EMRCREATECOLORSPACEW *pRec = (EMRCREATECOLORSPACEW*)m_pRecord; // MSDN: see "Basic ICM 2.0 Functions for Use Within a Device Context" // TODO_EMF: Place code here to handle EMF record SCPlayRecord(); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSETCOLORSPACE() { // TRACE0("**EMR_SETCOLORSPACE\n"); ASSERT(m_pRenderer); // EMRSELECTCOLORSPACE *pRec = (EMRSELECTCOLORSPACE*)m_pRecord; // MSDN: see "Basic ICM 2.0 Functions for Use Within a Device Context" // TODO_EMF: Place code here to handle EMF record SCPlayRecord(); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfDELETECOLORSPACE() { // TRACE0("**EMR_DELETECOLORSPACE\n"); ASSERT(m_pRenderer); // EMRDELETECOLORSPACE *pRec = (EMRDELETECOLORSPACE*)m_pRecord; // MSDN: see "Basic ICM 2.0 Functions for Use Within a Device Context" // TODO_EMF: Place code here to handle EMF record SCPlayRecord(); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfGLSRECORD() { // TRACE0("**EMR_GLSRECORD\n"); ASSERT(m_pRenderer); SC_BRKRESULT error(SC_BRK_NOERROR); EMRGLSRECORD *pRec = (EMRGLSRECORD*)m_pRecord; // TODO_EMF: Place code here to handle EMF record SCPlayRecord(); return error; } SC_BRKRESULT CSCEMFgdiParser::OnEmfGLSBOUNDEDRECORD() { // TRACE0("**EMR_GLSBOUNDEDRECORD\n"); ASSERT(m_pRenderer); // EMRGLSBOUNDEDRECORD *pRec = (EMRGLSBOUNDEDRECORD*)m_pRecord; // TODO_EMF: Place code here to handle EMF record SCPlayRecord(); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfPIXELFORMAT() { // TRACE0("**EMR_PIXELFORMAT\n"); ASSERT(m_pRenderer); // EMRPIXELFORMAT *pRec = (EMRPIXELFORMAT*)m_pRecord; // TODO_EMF: Place code here to handle EMF record SCPlayRecord(); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfDRAWESCAPE() { // TRACE0("**EMR_DRAWESCAPE\n"); ASSERT(m_pRenderer); // EMR *pRec = (EMR*)m_pRecord; // Do not play Escape // Anyway, now it's SCEMF_RESERVED_105 return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfEXTESCAPE() { // TRACE0("**EMR_EXTESCAPE\n"); ASSERT(m_pRenderer); // EMR *pRec = (EMR*)m_pRecord; // Do not play Escape // Anyway, now it's SCEMF_RESERVED_106 return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSTARTDOC() { // TRACE0("**EMR_STARTDOC\n"); ASSERT(m_pRenderer); // EMR *pRec = (EMR*)m_pRecord; // Do not play Escape // Anyway, now it's SCEMF_RESERVED_107 return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSMALLTEXTOUT() { // TRACE0("**EMR_SMALLTEXTOUT\n"); ASSERT(m_pRenderer); // WARNING: it's SCEMF_RESERVED_108 SCEMRSMALLTEXTOUTA *pRec = (SCEMRSMALLTEXTOUTA*)m_pRecord; // TODO: review this line SCEMRSMALLTEXTOUTA2 *pTextRec2 = (SCEMRSMALLTEXTOUTA2*)m_pRecord; // get the EMRTEXT SCEMRSMALLTEXTOUTA *pTextRec = pRec; // number of characters INT iNbChars = pTextRec->nChars; if (iNbChars<=0) { // We don't know the behavior of ExtTextOut: // - if number of characters is 0 // - if, moreover, TA_UPDATECP is set in the DC #if 0 // if required, play the record SCPlayRecord(); #endif return SC_BRK_NOERROR; } UINT uiOptions = pRec->fOptions; // we might have to alter it // TODO: review this line BOOL bUnicode = (uiOptions == 0x100); // Build the string LPWSTR pwStr = NULL; if (bUnicode) { // The string is in unicode -> we let it as is. // Offset is from the beginning of the struct and is in bytes. // // Get the unicode string pwStr = (LPWSTR)pTextRec->Text; #if 0 // TODO: // Translate glyph indices to code points when the rasterizer does not // support string measurement for glyph indices. if ((uiOptions & ETO_GLYPH_INDEX) && (!m_pRenderer->SCCanMeasureGlyphs()) { int iRes = SCUnicodeCharsFromGlyphs(m_hPlayDC, pString, iNbChars); if (iRes) uiOptions &= ~ETO_GLYPH_INDEX; } #endif } else { // The string is single-byte encoded. // Get adress of the string then construct the string. LPSTR pString = (LPSTR)pTextRec->Text; // TODO: review this line if (uiOptions==0x204) pString = (char *)pTextRec2->Text; pwStr = new wchar_t[iNbChars+1]; if (pwStr) {// We will use UNICODE strings exclusively pwStr[iNbChars] = 0; int iNum = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pString, iNbChars, pwStr, iNbChars+1); #ifdef _DEBUG if (0==iNum) { DWORD dwError = GetLastError(); } #endif ASSERT(iNum==iNbChars); } } ASSERT(pwStr); // Get intercharacter spacing array. // Be careful ! there are cases where OffDx==0. // TODO: review this line DWORD OffDx = 0;//pTextRec->offDx; INT *lpDx = (INT*)((BYTE*)pRec + OffDx); //if (0==OffDx) { // If the lpDx parameter is NULL, the ExtTextOut function uses the default // spacing between characters. So we do. // // Compute intercharacter spacing, based on each character width. lpDx = new INT[iNbChars]; BOOL bOk = SCGetTextCharWidthsW(m_hPlayDC, pwStr, iNbChars, lpDx); ASSERT(bOk); } // else use distances between origins of adjacent character cells as passed to ExtTextOut. CRect rcText; if (uiOptions==0x204) { rcText.CopyRect((LPRECT)&pTextRec2->rclBoundsSC); } else { uiOptions &= ~ETO_CLIPPED; // we don't have the rectangle rcText.SetRectEmpty(); } if (GM_COMPATIBLE==pTextRec->iGraphicsMode) m_pRenderer->SCDrawText(pTextRec->ptlReference.x, pTextRec->ptlReference.y, uiOptions, (LPRECT)&rcText, pwStr, iNbChars, lpDx, pRec->exScale, pRec->eyScale); else m_pRenderer->SCDrawText(pTextRec->ptlReference.x, pTextRec->ptlReference.y, uiOptions, (LPRECT)&rcText, pwStr, iNbChars, lpDx, 1, 1); // Clean up if (!bUnicode) delete [] pwStr; if (0==OffDx) delete [] lpDx; return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfFORCEUFIMAPPING() { // TRACE0("**EMR_FORCEUFIMAPPING\n"); ASSERT(m_pRenderer); // EMR *pRec = (EMR*)m_pRecord; // Danger if it writes to the DC // Worse if it attempts escape-like behavior //SCPlayRecord(); // Anyway, now it's SCEMF_RESERVED_109 return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfNAMEDESCAPE() { // TRACE0("**EMR_NAMEDESCAPE\n"); ASSERT(m_pRenderer); // Do not play escape // Anyway, now it's SCEMF_RESERVED_110 return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfCOLORCORRECTPALETTE() { // TRACE0("**EMR_COLORCORRECTPALETTE\n"); ASSERT(m_pRenderer); // EMR *pRec = (EMR*)m_pRecord; // TODO_EMF: Place code here to handle EMF record SCPlayRecord(); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSETICMPROFILEA() { // TRACE0("**EMR_SETICMPROFILEA\n"); ASSERT(m_pRenderer); // EMR *pRec = (EMR*)m_pRecord; // TODO_EMF: Place code here to handle EMF record SCPlayRecord(); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSETICMPROFILEW() { // TRACE0("**EMR_SETICMPROFILEW\n"); ASSERT(m_pRenderer); // EMR *pRec = (EMR*)m_pRecord; // TODO_EMF: Place code here to handle EMF record SCPlayRecord(); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfALPHABLEND() { // TRACE0("**EMR_ALPHABLEND\n"); ASSERT(m_pRenderer); EMRALPHABLEND *pRec = (EMRALPHABLEND*)m_pRecord; ASSERT(pRec->offBmiSrc && pRec->offBitsSrc); // Check if there is a bitmap if (pRec->offBmiSrc && pRec->offBitsSrc) { // Source CRect RcSrc(pRec->xSrc, pRec->ySrc, pRec->xSrc + pRec->cxSrc, pRec->ySrc + pRec->cySrc); BITMAPINFO *pBmi = (BITMAPINFO *) ((BYTE *)pRec + pRec->offBmiSrc); BYTE *pBits = (BYTE *) ((BYTE *) pRec + pRec->offBitsSrc); // Destination CRect RcDest(pRec->xDest, pRec->yDest, pRec->xDest + pRec->cxDest, pRec->yDest + pRec->cyDest); m_pRenderer->SCDrawImageAlpha(&RcDest, &RcSrc, pBits, pBmi, pRec->iUsageSrc, pRec->dwRop, &pRec->xformSrc, pRec->crBkColorSrc); } return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfALPHADIBBLEND() { // TRACE0("**EMR_SETLAYOUT\n"); ASSERT(m_pRenderer); // Now it's SCEMF_SETLAYOUT //DWORD SetLayout( // HDC hdc, // handle to DC // DWORD dwLayout, // layout options // ); // dwLayout==LAYOUT_BITMAPORIENTATIONPRESERVED Disables any reflection during BitBlt // and StretchBlt operations. // LAYOUT_RTL Sets the default horizontal layout // to be right to left. // OSes: Windows 2000 and later, Windows 98 and later // TODO_EMF: horizontal reflection when the LAYOUT_RTL flag is selected // m_pRenderer->SCSetLayout(((EMRSETLAYOUT*)m_pRecord)->iMode); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfTRANSPARENTBLT() { // TRACE0("**EMR_TRANSPARENTBLT\n"); ASSERT(m_pRenderer); EMRTRANSPARENTBLT *pRec = (EMRTRANSPARENTBLT*)m_pRecord; ASSERT(pRec->offBmiSrc && pRec->offBitsSrc); // Check if there is a bitmap if (pRec->offBmiSrc && pRec->offBitsSrc) { // Source CRect RcSrc(pRec->xSrc, pRec->ySrc, pRec->xSrc + pRec->cxSrc, pRec->ySrc + pRec->cySrc); BITMAPINFO *pBmi = (BITMAPINFO *) ((BYTE *)pRec + pRec->offBmiSrc); BYTE *pBits = (BYTE *) ((BYTE *) pRec + pRec->offBitsSrc); // Destination CRect RcDest(pRec->xDest, pRec->yDest, pRec->xDest + pRec->cxDest, pRec->yDest + pRec->cyDest); m_pRenderer->SCDrawImageTransparent(&RcDest, &RcSrc, pBits, pBmi, pRec->iUsageSrc, pRec->dwRop, &pRec->xformSrc, pRec->crBkColorSrc); } return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfTRANSPARENTDIB() { // TRACE0("**EMR_TRANSPARENTDIB\n"); ASSERT(m_pRenderer); // EMR *pRec = (EMR*)m_pRecord; // TODO_EMF: Place code here to handle EMF record // Anyway, now it's SCEMF_RESERVED_117 return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfGRADIENTFILL() { // TRACE0("**EMR_GRADIENTFILL\n"); ASSERT(m_pRenderer); EMRGRADIENTFILL *pRec = (EMRGRADIENTFILL*)m_pRecord; LPBYTE pMesh = (LPBYTE)&pRec->Ver[pRec->nVer]; m_pRenderer->SCGradientFill(pRec->Ver, pRec->nVer, pMesh, pRec->nTri, pRec->ulMode); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSETLINKEDUFIS() { // TRACE0("**EMR_SETLINKEDUFIS\n"); ASSERT(m_pRenderer); // EMR *pRec = (EMR*)m_pRecord; // TODO_EMF: Place code here to handle EMF record SCPlayRecord(); // Anyway, now it's SCEMF_RESERVED_119 return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfSETTEXTJUSTIFICATION() { // TRACE0("**EMR_SETTEXTJUSTIFICATION\n"); ASSERT(m_pRenderer); // EMR *pRec = (EMR*)m_pRecord; // TODO_EMF: Place code here to handle EMF record SCPlayRecord(); // Anyway, now it's SCEMF_RESERVED_120 return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnEmfCOLORMATCHTOTARGETW() { // TRACE0("**EMR_CREATECOLORSPACE\n"); ASSERT(m_pRenderer); // COLORMATCHTOTARGETW *pRec = (COLORMATCHTOTARGETW*)m_pRecord; // TODO_EMF: Place code here to handle EMF record SCPlayRecord(); return SC_BRK_NOERROR; } SC_BRKRESULT CSCEMFgdiParser::OnBrkUNKRecord(long lMsg) { // TRACE0("**OnBrkUNKRecord\n"); ASSERT(m_pRenderer); UNUSED(lMsg); // unused in release builds // By default, play unkown record SCPlayRecord(); return SC_BRK_NOERROR; } ////////////////////////////////////////////////////////////////////// // Helpers ////////////////////////////////////////////////////////////////////// // called before enumeration SC_BRKRESULT CSCEMFgdiParser::SCBeginBreak(HDC hDC, LPVOID lpData, CONST RECT *lpRect) { SC_BRKRESULT error(SC_BRK_NOERROR); ASSERT(m_pRenderer); if (!m_pRenderer) return SC_BRK_NORENDERER; GetWorldTransform(hDC, &m_xformOrig); // call inherited error = SCBrkEMF::SCBeginBreak(hDC, lpData, lpRect); // before enumeration // clone the DC so that this class does not write on the destination DC m_hDestDC = hDC; // for GDI+ #ifdef SC_USE_DCCLONER // TODO: fix the bitmap problem in the cloner m_pCloneDC = new SCDCCloner(hDC); ASSERT(m_pCloneDC); m_hPlayDC = m_pCloneDC->SCGetHDC(); // for GDI #else m_hPlayDC = hDC; // for GDI #endif ASSERT(m_hPlayDC && m_hDestDC); return error; } ////////////////////////////////////////////////////////////////////// // Message map ////////////////////////////////////////////////////////////////////// SC_BEGIN_MESSAGE_MAP(CSCEMFgdiParser, SCBrkEMF) ON_VECTRECORD(SCEMF_HEADER, OnEmfHEADER) ON_VECTRECORD(SCEMF_POLYBEZIER, OnEmfPOLYBEZIER) ON_VECTRECORD(SCEMF_POLYGON, OnEmfPOLYGON) ON_VECTRECORD(SCEMF_POLYLINE, OnEmfPOLYLINE) ON_VECTRECORD(SCEMF_POLYBEZIERTO, OnEmfPOLYBEZIERTO) ON_VECTRECORD(SCEMF_POLYLINETO, OnEmfPOLYLINETO) ON_VECTRECORD(SCEMF_POLYPOLYLINE, OnEmfPOLYPOLYLINE) ON_VECTRECORD(SCEMF_POLYPOLYGON, OnEmfPOLYPOLYGON) ON_VECTRECORD(SCEMF_SETWINDOWEXTEX, OnEmfSETWINDOWEXTEX) ON_VECTRECORD(SCEMF_SETWINDOWORGEX, OnEmfSETWINDOWORGEX) ON_VECTRECORD(SCEMF_SETVIEWPORTEXTEX, OnEmfSETVIEWPORTEXTEX) ON_VECTRECORD(SCEMF_SETVIEWPORTORGEX, OnEmfSETVIEWPORTORGEX) ON_VECTRECORD(SCEMF_SETBRUSHORGEX, OnEmfSETBRUSHORGEX) ON_VECTRECORD(SCEMF_EOF, OnEmfEOF) ON_VECTRECORD(SCEMF_SETPIXELV, OnEmfSETPIXELV) ON_VECTRECORD(SCEMF_SETMAPPERFLAGS, OnEmfSETMAPPERFLAGS) ON_VECTRECORD(SCEMF_SETMAPMODE, OnEmfSETMAPMODE) ON_VECTRECORD(SCEMF_SETBKMODE, OnEmfSETBKMODE) ON_VECTRECORD(SCEMF_SETPOLYFILLMODE, OnEmfSETPOLYFILLMODE) ON_VECTRECORD(SCEMF_SETROP2, OnEmfSETROP2) ON_VECTRECORD(SCEMF_SETSTRETCHBLTMODE, OnEmfSETSTRETCHBLTMODE) ON_VECTRECORD(SCEMF_SETTEXTALIGN, OnEmfSETTEXTALIGN) ON_VECTRECORD(SCEMF_SETCOLORADJUSTMENT, OnEmfSETCOLORADJUSTMENT) ON_VECTRECORD(SCEMF_SETTEXTCOLOR, OnEmfSETTEXTCOLOR) ON_VECTRECORD(SCEMF_SETBKCOLOR, OnEmfSETBKCOLOR) ON_VECTRECORD(SCEMF_OFFSETCLIPRGN, OnEmfOFFSETCLIPRGN) ON_VECTRECORD(SCEMF_MOVETOEX, OnEmfMOVETOEX) ON_VECTRECORD(SCEMF_SETMETARGN, OnEmfSETMETARGN) ON_VECTRECORD(SCEMF_EXCLUDECLIPRECT, OnEmfEXCLUDECLIPRECT) ON_VECTRECORD(SCEMF_INTERSECTCLIPRECT, OnEmfINTERSECTCLIPRECT) ON_VECTRECORD(SCEMF_SCALEVIEWPORTEXTEX, OnEmfSCALEVIEWPORTEXTEX) ON_VECTRECORD(SCEMF_SCALEWINDOWEXTEX, OnEmfSCALEWINDOWEXTEX) ON_VECTRECORD(SCEMF_SAVEDC, OnEmfSAVEDC) ON_VECTRECORD(SCEMF_RESTOREDC, OnEmfRESTOREDC) ON_VECTRECORD(SCEMF_SETWORLDTRANSFORM, OnEmfSETWORLDTRANSFORM) ON_VECTRECORD(SCEMF_MODIFYWORLDTRANSFORM, OnEmfMODIFYWORLDTRANSFORM) ON_VECTRECORD(SCEMF_SELECTOBJECT, OnEmfSELECTOBJECT) ON_VECTRECORD(SCEMF_CREATEPEN, OnEmfCREATEPEN) ON_VECTRECORD(SCEMF_CREATEBRUSHINDIRECT, OnEmfCREATEBRUSHINDIRECT) ON_VECTRECORD(SCEMF_DELETEOBJECT, OnEmfDELETEOBJECT) ON_VECTRECORD(SCEMF_ANGLEARC, OnEmfANGLEARC) ON_VECTRECORD(SCEMF_ELLIPSE, OnEmfELLIPSE) ON_VECTRECORD(SCEMF_RECTANGLE, OnEmfRECTANGLE) ON_VECTRECORD(SCEMF_ROUNDRECT, OnEmfROUNDRECT) ON_VECTRECORD(SCEMF_ARC, OnEmfARC) ON_VECTRECORD(SCEMF_CHORD, OnEmfCHORD) ON_VECTRECORD(SCEMF_PIE, OnEmfPIE) ON_VECTRECORD(SCEMF_SELECTPALETTE, OnEmfSELECTPALETTE) ON_VECTRECORD(SCEMF_CREATEPALETTE, OnEmfCREATEPALETTE) ON_VECTRECORD(SCEMF_SETPALETTEENTRIES, OnEmfSETPALETTEENTRIES) ON_VECTRECORD(SCEMF_RESIZEPALETTE, OnEmfRESIZEPALETTE) ON_VECTRECORD(SCEMF_REALIZEPALETTE, OnEmfREALIZEPALETTE) ON_VECTRECORD(SCEMF_EXTFLOODFILL, OnEmfEXTFLOODFILL) ON_VECTRECORD(SCEMF_LINETO, OnEmfLINETO) ON_VECTRECORD(SCEMF_ARCTO, OnEmfARCTO) ON_VECTRECORD(SCEMF_POLYDRAW, OnEmfPOLYDRAW) ON_VECTRECORD(SCEMF_SETARCDIRECTION, OnEmfSETARCDIRECTION) ON_VECTRECORD(SCEMF_SETMITERLIMIT, OnEmfSETMITERLIMIT) ON_VECTRECORD(SCEMF_BEGINPATH, OnEmfBEGINPATH) ON_VECTRECORD(SCEMF_ENDPATH, OnEmfENDPATH) ON_VECTRECORD(SCEMF_CLOSEFIGURE, OnEmfCLOSEFIGURE) ON_VECTRECORD(SCEMF_FILLPATH, OnEmfFILLPATH) ON_VECTRECORD(SCEMF_STROKEANDFILLPATH, OnEmfSTROKEANDFILLPATH) ON_VECTRECORD(SCEMF_STROKEPATH, OnEmfSTROKEPATH) ON_VECTRECORD(SCEMF_FLATTENPATH, OnEmfFLATTENPATH) ON_VECTRECORD(SCEMF_WIDENPATH, OnEmfWIDENPATH) ON_VECTRECORD(SCEMF_SELECTCLIPPATH, OnEmfSELECTCLIPPATH) ON_VECTRECORD(SCEMF_ABORTPATH, OnEmfABORTPATH) ON_VECTRECORD(SCEMF_GDICOMMENT, OnEmfGDICOMMENT) ON_VECTRECORD(SCEMF_FILLRGN, OnEmfFILLRGN) ON_VECTRECORD(SCEMF_FRAMERGN, OnEmfFRAMERGN) ON_VECTRECORD(SCEMF_INVERTRGN, OnEmfINVERTRGN) ON_VECTRECORD(SCEMF_PAINTRGN, OnEmfPAINTRGN) ON_VECTRECORD(SCEMF_EXTSELECTCLIPRGN, OnEmfEXTSELECTCLIPRGN) ON_VECTRECORD(SCEMF_BITBLT, OnEmfBITBLT) ON_VECTRECORD(SCEMF_STRETCHBLT, OnEmfSTRETCHBLT) ON_VECTRECORD(SCEMF_MASKBLT, OnEmfMASKBLT) ON_VECTRECORD(SCEMF_PLGBLT, OnEmfPLGBLT) ON_VECTRECORD(SCEMF_SETDIBITSTODEVICE, OnEmfSETDIBITSTODEVICE) ON_VECTRECORD(SCEMF_STRETCHDIBITS, OnEmfSTRETCHDIBITS) ON_VECTRECORD(SCEMF_EXTCREATEFONTINDIRECTW, OnEmfEXTCREATEFONTINDIRECTW) ON_VECTRECORD(SCEMF_EXTTEXTOUTA, OnEmfEXTTEXTOUTA) ON_VECTRECORD(SCEMF_EXTTEXTOUTW, OnEmfEXTTEXTOUTW) ON_VECTRECORD(SCEMF_POLYBEZIER16, OnEmfPOLYBEZIER16) ON_VECTRECORD(SCEMF_POLYGON16, OnEmfPOLYGON16) ON_VECTRECORD(SCEMF_POLYLINE16, OnEmfPOLYLINE16) ON_VECTRECORD(SCEMF_POLYBEZIERTO16, OnEmfPOLYBEZIERTO16) ON_VECTRECORD(SCEMF_POLYLINETO16, OnEmfPOLYLINETO16) ON_VECTRECORD(SCEMF_POLYPOLYLINE16, OnEmfPOLYPOLYLINE16) ON_VECTRECORD(SCEMF_POLYPOLYGON16, OnEmfPOLYPOLYGON16) ON_VECTRECORD(SCEMF_POLYDRAW16, OnEmfPOLYDRAW16) ON_VECTRECORD(SCEMF_CREATEMONOBRUSH, OnEmfCREATEMONOBRUSH) ON_VECTRECORD(SCEMF_CREATEDIBPATTERNBRUSHPT, OnEmfCREATEDIBPATTERNBRUSHPT) ON_VECTRECORD(SCEMF_EXTCREATEPEN, OnEmfEXTCREATEPEN) ON_VECTRECORD(SCEMF_POLYTEXTOUTA, OnEmfPOLYTEXTOUTA) ON_VECTRECORD(SCEMF_POLYTEXTOUTW, OnEmfPOLYTEXTOUTW) ON_VECTRECORD(SCEMF_SETICMMODE, OnEmfSETICMMODE) ON_VECTRECORD(SCEMF_CREATECOLORSPACE, OnEmfCREATECOLORSPACE) ON_VECTRECORD(SCEMF_SETCOLORSPACE, OnEmfSETCOLORSPACE) ON_VECTRECORD(SCEMF_DELETECOLORSPACE, OnEmfDELETECOLORSPACE) ON_VECTRECORD(SCEMF_GLSRECORD, OnEmfGLSRECORD) ON_VECTRECORD(SCEMF_GLSBOUNDEDRECORD, OnEmfGLSBOUNDEDRECORD) ON_VECTRECORD(SCEMF_PIXELFORMAT, OnEmfPIXELFORMAT) ON_VECTRECORD(SCEMF_DRAWESCAPE, OnEmfDRAWESCAPE) ON_VECTRECORD(SCEMF_EXTESCAPE, OnEmfEXTESCAPE) ON_VECTRECORD(SCEMF_STARTDOC, OnEmfSTARTDOC) ON_VECTRECORD(SCEMF_SMALLTEXTOUT, OnEmfSMALLTEXTOUT) ON_VECTRECORD(SCEMF_FORCEUFIMAPPING, OnEmfFORCEUFIMAPPING) ON_VECTRECORD(SCEMF_NAMEDESCAPE, OnEmfNAMEDESCAPE) ON_VECTRECORD(SCEMF_COLORCORRECTPALETTE, OnEmfCOLORCORRECTPALETTE) ON_VECTRECORD(SCEMF_SETICMPROFILEA, OnEmfSETICMPROFILEA) ON_VECTRECORD(SCEMF_SETICMPROFILEW, OnEmfSETICMPROFILEW) ON_VECTRECORD(SCEMF_ALPHABLEND, OnEmfALPHABLEND) ON_VECTRECORD(SCEMF_ALPHADIBBLEND, OnEmfALPHADIBBLEND) ON_VECTRECORD(SCEMF_TRANSPARENTBLT, OnEmfTRANSPARENTBLT) ON_VECTRECORD(SCEMF_TRANSPARENTDIB, OnEmfTRANSPARENTDIB) ON_VECTRECORD(SCEMF_GRADIENTFILL, OnEmfGRADIENTFILL) ON_VECTRECORD(SCEMF_SETLINKEDUFIS, OnEmfSETLINKEDUFIS) ON_VECTRECORD(SCEMF_SETTEXTJUSTIFICATION, OnEmfSETTEXTJUSTIFICATION) ON_VECTRECORD(SCEMF_COLORMATCHTOTARGETW, OnEmfCOLORMATCHTOTARGETW) ON_VECTRECORD(SCEMF_CREATECOLORSPACEW, OnEmfCREATECOLORSPACEW) SC_END_MESSAGE_MAP()